local Lang = require("common.Lang")
local Msg = require("core.Msg")
local Human = require("core.Human")
local Timer = require("core.Timer")
local Broadcast = require("broadcast.Broadcast")
local sbConfig = require("excel.Shenbing")
local InnerDataManager = require("innerdata.InnerDataManagerFW")
local InnerDataDefine = require("innerdata.Define")
local BufferNotify = require("buffer.Utils")
local CopyCallbackW = require("copy.CallbackW")
local Config = require("Config")
local PfLogic = require("tencentApi.PfLogic")




TEAM_MAX_MEMBER_COUNT = 3							--// 最大队伍人数

TEAM_PICK_WEIGHT = 100								--组队拾取权重
TEAM_PICK_MIN_WEIGHT = 25							--组队拾取最低权重
TEAM_PRICK_WEIGHT_RATE = 0.5						--组队拾取权重率

TEAM_OFFLINE_KILL_TIME = 120000						-- 120s不在线就踢出队伍
TEAM_MEMBER_REFRESH_TIME = 1						-- 5s信息同步

Team = Team or {}									-- 队伍信息列表  { id,uuid,count,members,}
Uuid2Team = Uuid2Team or {}							-- 通过角色名查找角色所在队伍ID 
TeamID= TeamID or 1									-- 队伍id计数器 每次+1

-- 根据玩家名字获取其所在队伍信息
function getTeamByUuid(uuid)
	return Uuid2Team[uuid]
end

-- 根据teamID获取其所在队伍信息
function getTeamByTeamID(teamID)
	return Team[teamID]
end

-- 判断是否在同一个队伍里
function inSameTeam(uuid1,uuid2)
	local team1 = getTeamByUuid(uuid1)
	local team2 = getTeamByUuid(uuid2)
	if team1 and team1 == team2 then
		return true
	end
	return false
end

function refreshFFI(team)
  if team == nil then
    return
  end

  for i = 1, team.count do
    local member = Human.onlineUuid[team[i].uuid]
    if member then
      member.db.teamUuidLen = team.count
      for j = 1, team.count do
        member.db.teamUuid[j-1].uuid = team[j].uuid
      end
    end
  end
end



-- 对特定人下发队伍成员信息
function sendList(human)
	local team = getTeamByUuid(human._id)
	if team == nil then
		return
	end
	
	local msgRet = Msg.gc.GC_TEAM_LIST
	msgRet.members[0] = 0
	local onlineUuid = Human.onlineUuid
	for i = 1, TEAM_MAX_MEMBER_COUNT do
		if team[i] ~= nil then
			msgRet.members[0] = msgRet.members[0] + 1
			local len = msgRet.members[0]
			msgRet.members[len].name = team[i].name
			msgRet.members[len].sex = team[i].sex
			msgRet.members[len].uuid = team[i].uuid
			msgRet.members[len].args = 0
			if i == 1 then
			   msgRet.members[len].leader = 1
			else
			   msgRet.members[len].leader = 0
			end
			local member = onlineUuid[team[i].uuid]
			if member ~= nil then
				msgRet.members[len].id = member.id
				msgRet.members[len].online = 1
				msgRet.members[len].away = member.scene_id ~= human.scene_id and 0 or 1
				if member.teamCopyAfk then
					msgRet.members[len].afk = 1
				else
					msgRet.members[len].afk = 0
				end
				msgRet.members[len].level = member.db.lv
				msgRet.members[len].mapID = member.db.map_id 
				msgRet.members[len].sceneID = member.scene_id or 0
				msgRet.members[len].x = member.db.x 
				msgRet.members[len].y = member.db.y 
				msgRet.members[len].hp = member.db.hp
				msgRet.members[len].mp = member.db.mp
				msgRet.members[len].hpMax = member.db.MaxHp
				msgRet.members[len].mpMax = member.db.MaxMp
				msgRet.members[len].buff[0] = 0				
				BufferNotify.setBufferList(member,msgRet.members[len].buff)			
				msgRet.members[len].shenbingName = Human.getShenbingName(member)
		    if PfLogic.isYellowShow(member) then
          msgRet.members[len].yellowVipLv = member.db.yellowVipLv or 0
          msgRet.members[len].yellowYearVip = member.db.yellowYearVip or 0
        else
          msgRet.members[len].yellowVipLv = 0
          msgRet.members[len].yellowYearVip = 0
        end
        if PfLogic.isBlueShow(human) then
          msgRet.members[len].blueVipLv = member.db.blueVipLv or 0
          msgRet.members[len].blueYearVip = member.db.blueYearVip or 0 
          msgRet.members[len].blueSuperVip = member.db.blueSuperVip or 0 
          if PfLogic.is3366Show(human) then
              msgRet.members[len].level3366 = member.db.blueSuperVip
          else
              msgRet.members[len].level3366 = 0
          end
        else
          msgRet.members[len].blueVipLv = 0
          msgRet.members[len].blueYearVip = 0 
          msgRet.members[len].blueSuperVip = 0 
          msgRet.members[len].level3366 = 0
        end
			else
				msgRet.members[len].id = -1
				msgRet.members[len].online = 0
				msgRet.members[len].away = 0 
				
				msgRet.members[len].afk = 0
				msgRet.members[len].level = 0
				msgRet.members[len].mapID = 0
				msgRet.members[len].sceneID = 0
				msgRet.members[len].x = 0
				msgRet.members[len].y = 0
				msgRet.members[len].hp = 0
				msgRet.members[len].mp = 0
				msgRet.members[len].hpMax = 0
				msgRet.members[len].mpMax = 0
				msgRet.members[len].buff[0] = 0
				msgRet.members[len].shenbingName = ""
			  msgRet.members[len].yellowVipLv =  0
        msgRet.members[len].yellowYearVip = 0
        msgRet.members[len].blueVipLv = 0
        msgRet.members[len].blueYearVip = 0
        msgRet.members[len].blueSuperVip = 0  
        msgRet.members[len].level3366 = 0
			end
		end
	end
	Msg.send(msgRet, human.fd)	
end

local function getNewMemberTable(human)
	return {uuid=human._id,account=human.account, name=human.name,lv=human.db.lv,sex=human.db.sex,offlineTime = 0, enterTime = Timer.now}
end

-- 创建一个新队伍
function create(leader)
	local team = {}
	team.id = TeamID
	TeamID = TeamID + 1
	team.count = 1
	team[1] = getNewMemberTable(leader)

	Team[team.id] = team
	Uuid2Team[leader._id] = team
	refreshFFI(team)
	--组队拾取权重
	leader.teamPickWeight = TEAM_PICK_WEIGHT

	return team
end


-- 队伍进人
function addMember(team,member)
	for i = 2, TEAM_MAX_MEMBER_COUNT do
		if not team[i] then
			onAddMemberBeforeCB(team, member._id)
		
			team[i] = getNewMemberTable(member)
			Uuid2Team[member._id] = team
			team.count = team.count + 1
			
			refreshFFI(team)
			--组队拾取权重
			member.teamPickWeight = TEAM_PICK_WEIGHT
			
			onAddMemberAfterCB(team, member._id)
			
--			local name1,name2,name3,name4,name5 = getTeamNameInfoLog(team)
			--Log.write(Log.LOGID_OSS_TEAM,member._id,member.account,member.name,member.db.lv,name1,name2,name3,name4,name5,LogDefine.TEAM.ENTER)
			break
		end
	end
end

-- 队伍出人
function delMember(team, uuid)
	for i = 1, TEAM_MAX_MEMBER_COUNT do
		local exitMember = team[i]
		if exitMember ~= nil and exitMember.uuid == uuid then
			onDelMemberBeforeCB(team, uuid)
		
			team[i] = nil
			Uuid2Team[uuid] = nil
			team.count = team.count - 1
			for j = i, TEAM_MAX_MEMBER_COUNT - 1 do
				team[j] = team[j + 1]
			end
			team[TEAM_MAX_MEMBER_COUNT] = nil
			local member = Human.onlineUuid[uuid]
			if member then
            member.db.teamUuidLen = 0
      end
--			local name1,name2,name3,name4,name5 = getTeamNameInfoLog(team)
			--Log.write(Log.LOGID_OSS_TEAM,exitMember.uuid,exitMember.account,exitMember.name,exitMember.lv,name1,name2,name3,name4,name5,LogDefine.TEAM.EXIT)		
			
			onDelMemberAfterCB(team, uuid)
			
			refreshFFI(team)
			break
		end
	end
end

-- 退出队伍
function exit(uuid)

	local team = getTeamByUuid(uuid)
	if not team then
		return
	end

	local onlineUuid = Human.onlineUuid
	local exitHuman = onlineUuid[uuid]
	
	if team.count == 1 then
		dismiss(uuid)
		return
	end

	local oldLeaderUuid = getLeaderUuid(team)
	delMember(team, uuid)
	
	local newLeaderUuid = getLeaderUuid(team)
	local newLeaderName = getLeaderName(team)
	
	if oldLeaderUuid == newLeaderUuid then
		if exitHuman then
			Broadcast.sendBroadcastFDs(getTeamOnlineMemberFD(team),Lang.DOWN,exitHuman.name..Lang.TEAM_LEAVE_OK)
		end
	else
		--队长离队
		--笑一生离开了队伍，你被任命为队伍的队长。
		local newLeader = Human.onlineUuid[newLeaderUuid]
		if newLeader then
			if exitHuman then
				Broadcast.sendBroadcast(newLeader,Lang.DOWN,exitHuman.name .. Lang.TEAM_LEAVE_OK1)
			end
		end
		if exitHuman then
			Broadcast.sendBroadcastFDs(getTeamOnlineMemberFD(team,newLeaderUuid),Lang.DOWN,string.format(Lang.TEAM_LEAVE_OK2,exitHuman.name,newLeaderName))
		end
	end
	
	local msgRet = Msg.gc.GC_TEAM_EXIT
	msgRet.exitName = exitHuman and exitHuman.name or ""
	msgRet.exitUuid = uuid
	msgRet.newLeaderName = newLeaderName
	msgRet.newLeaderUuid = newLeaderUuid
	
	-- 通知离队人 离队成功
	if exitHuman then
		Msg.send(msgRet,exitHuman.fd)
	end
	
	sendLists(team)

	-- 通知队伍其他人 有人离队了
	Msg.sendMulti(msgRet, getTeamOnlineMemberFD(team))
	
	checkDismiss(team)
end

function checkDismiss(team)
	if team == nil or team.count > 1 then return end
	local leader = Human.onlineUuid[getLeaderUuid(team)]
	if leader then
		-- 如果一个人 并且不是在组队和夫妻副本中 那么退出队伍
--		local copyID = Copy.isCopyBySceneID(leader.scene_id)	
--		if copyID == nil or (CopyDefine.COPY_TYPE_TEAM ~= ExcelMapConf.copy[copyID].type and CopyDefine.COPY_TYPE_COUPLE ~= ExcelMapConf.copy[copyID].type) then
			dismiss(leader._id)
--		end
	end
end

-- 解散队伍（只为组队匹配模块使用 不发通知 不触发回调）
function dismissForCopyTeamSign(team)
	if not team then return end
	
	for i = 1, TEAM_MAX_MEMBER_COUNT do
		if team[i] ~= nil then
			Uuid2Team[team[i].uuid] = nil
			team[i] = nil
		end
	end
	Team[team.id] = nil
end

-- 组建队伍（只为组队匹配模块使用 不发通知 不触发回调）
function createTeamForTeamSign(humanList)
	local team = create(humanList[1], true)
	for i = 2, #humanList do
		team.count = team.count + 1
		local human = humanList[i]
		team[i] = getNewMemberTable(human)
		Uuid2Team[human._id] = team
	end
end

-- 队伍加人（只为组队匹配模块使用 不发通知 不触发回调）
function addMemberForTeamSign(team, human)
	for i = 2, TEAM_MAX_MEMBER_COUNT do
		if not team[i] then
			team[i] = getNewMemberTable(human)
			Uuid2Team[human._id] = team
			team.count = team.count + 1
			--组队拾取权重
			human.teamPickWeight = TEAM_PICK_WEIGHT
			break
		end
	end
end

-- 队长解散队伍
function dismiss(uuid)
	local team = getTeamByUuid(uuid)
	if not team then
		return
	end
	if getLeaderUuid(team) ~= uuid then
		return
	end
	--解散队伍回调
	onDismissCB(team)
	
	local msgRet = Msg.gc.GC_TEAM_DISMISS
	Msg.sendMulti(msgRet, getTeamOnlineMemberFD(team))
	for i = 1, TEAM_MAX_MEMBER_COUNT do
		if team[i] ~= nil then
			Uuid2Team[team[i].uuid] = nil
			local human = Human.onlineUuid[team[i].uuid]
			if human then
			   human.db.teamUuidLen = 0
			end
			team[i] = nil
		end
	end
	Team[team.id] = nil
end

-- 队长T人
function kick(leader,kickName,kickUuid)
	
	if not leader or not kickUuid or leader._id == kickUuid then
		return 
	end
	
	local onlineUuid = Human.onlineUuid
	local kickHuman = onlineUuid[kickUuid]
	
	local team = getTeamByUuid(leader._id)
	if not team then
		return 
	end
	
	if getLeaderUuid(team) ~= leader._id then
		return
	end
	
	local kickTeam = getTeamByUuid(kickUuid)
	if team ~= kickTeam then
		return
	end
	
	
	delMember(team, kickUuid)
	
	-- 通知队伍 有人被踢了
	local msgRet = Msg.gc.GC_TEAM_MEMBER_KICK
	msgRet.name = kickName
	msgRet.uuid = kickUuid
	--Msg.sendMulti(msgRet, getTeamOnlineMemberFD(team))
	Broadcast.sendBroadcastFDs(getTeamOnlineMemberFD(team),Lang.DOWN,kickName..Lang.TEAM_LEAVE_OK)
	
	-- 通知被踢人 他被踢了
	if kickHuman ~= nil and kickHuman.fd then
		Msg.send(msgRet,kickHuman.fd)
		Broadcast.sendBroadcast(kickHuman,Lang.DOWN,Lang.TEAM_KICKED)
	end 
				
	sendLists(team)
	
	checkDismiss(team)
	

end

-- 移交队长
function changeLeader(human,targetUuid)
	local team = getTeamByUuid(human._id)
	if not team then
		return 
	end
	
	local oldLeaderUuid = getLeaderUuid(team)
	if human._id ~= oldLeaderUuid then
		return
	end
	
	local newLeaderMember,index = getMember(team,targetUuid)
	local target = Human.onlineUuid[targetUuid]
	if not newLeaderMember or not target then
		return 
	end
	onChangeLeaderCB(team, human._id)
	table.remove(team,index)
	Broadcast.sendBroadcastFDs(getTeamOnlineMemberFD(team),Lang.DOWN,target.name..Lang.TEAM_BECOME_LEADER)
	Broadcast.sendBroadcast(target,Lang.DOWN, string.format(Lang.TEAM_BECOME_LEADER1,human.name))
	table.insert(team,1,newLeaderMember)
	sendLists(team)
	
end



-- 对队伍中的每个人下发队伍成员信息
function sendLists(team)
	if team == nil then
		return
	end
	
	local onlineUuid = Human.onlineUuid
	
	for i = 1, TEAM_MAX_MEMBER_COUNT do
		if team[i] ~= nil and onlineUuid[team[i].uuid] ~= nil then
			sendList(onlineUuid[team[i].uuid])
		end
	end
end

-- 获取队伍中在线玩家idlist
function getTeamOnlineMemberFD(team,withoutUuid)
	local ids = {}
	local index = 0
	local onlineUuid = Human.onlineUuid
	for i = 1, TEAM_MAX_MEMBER_COUNT do
		if team[i] ~= nil and onlineUuid[team[i].uuid] ~= nil and team[i].uuid ~= withoutUuid then
			if onlineUuid[team[i].uuid].fd then
				index = index + 1
				ids[index] = onlineUuid[team[i].uuid].fd
			end
		end
	end
	ids[0] = index
	return ids
end

-- 获取队长uuid
function getLeaderUuid(team)
	return team[1].uuid
end

-- 获取队长name
function getLeaderName(team)
	return team[1].name
end

--取成员
function getMember(team,targetUuid)
	for index=1,TEAM_MAX_MEMBER_COUNT do 
		local teamMember = team[index] 
		if teamMember and teamMember.uuid == targetUuid then
			return teamMember,index
		end
	end
end

-- 把包发送给队伍里所有人(在线)
function sendMsg2Member(human, msg)
	local team = getTeamByUuid(human._id)
	if not team then
		return
	end
	
	local send_msg = Msg.gc.GC_CHAT
	send_msg.msg_type = msg.msg_type  
  send_msg.role_name = msg.role_name
  send_msg.obj_id = msg.obj_id
  send_msg.uuid = msg.uuid  
  send_msg.msg = msg.msg
  send_msg.level3366 = human.db.level3366
  send_msg.args = 0
  local bluelv = 0
  if human.db.blueVip ~=0 then
    bluelv = human.db.blueVipLv
  end 
  send_msg.blue = string.format("%d%d%d", bluelv, human.db.blueYearVip, human.db.blueSuperVip) 
  
	local onlineUuid = Human.onlineUuid
	local list = Msg.list
	local len = 0
	for i = 1, TEAM_MAX_MEMBER_COUNT do
		if team[i] then
			local t = onlineUuid[team[i].uuid]
			if t and t.fd then
				len = len + 1
				list[len] = t.fd
			end
		end
	end
	list[0] = len
	Msg.sendMulti(send_msg, list)
end


function onUserLogin(human)
	local team = getTeamByUuid(human._id)
	if team and not Config.IS_MIDDLE then  
	   checkDismiss(team) -- 可能会出现上线只有自己一个人的队伍，
	end
	team = getTeamByUuid(human._id)
	if team then
		sendLists(team)
		onUserOnlineCB(team, human._id)
		refreshFFI(team)
  else
    human.db.teamUuidLen = 0
	end
end


-- 角色登出
function onUserLogOut(human)
	
	local team = getTeamByUuid(human._id)
	if not team then
		return
	end
	
	local onlineUuid = Human.onlineUuid
	local msgRet = Msg.gc.GC_TEAM_DISCONNECT
	
	for k,v in ipairs(team) do 
		if v.uuid == human._id then
			v.offlineTime = Timer.now
		else	
			local member = onlineUuid[v.uuid]
			if member then
				msgRet.name = human.name
				msgRet.uuid = human._id
				Msg.send(msgRet,member.fd)
			end	
		end		
	end

	-- 如果是队长 那么把队长移交给下一位
	if team.count > 1 and getLeaderUuid(team) == human._id then
		for k, v in ipairs(team) do
			local member = onlineUuid[v.uuid]
			if member and v.uuid ~= human._id then
				if member.teamCopyAfk == nil then
					changeLeader(human, member._id)
					break
				end
			end	
		end
	end
	
end

-- 检查T成员
local function checkOffline(team)
	local now = Timer.now
	local onlineUuid = Human.onlineUuid 

	local change = false
	for k ,v in ipairs(team) do 
		local member = onlineUuid[v.uuid]
		if member and member.fd then
			if v.offlineTime ~= 0 then
				v.offlineTime = 0 
				change = true
			end
		else
			if v.offlineTime ~= 0 and now - v.offlineTime >= TEAM_OFFLINE_KILL_TIME then 
				exit(v.uuid)
			end
		end
	end
	
	return change
end

--成员信息刷新
local function memberRefresh(team)
	local now = Timer.now
	if not team.memberRefreshTime then
		team.memberRefreshTime = now
	end
	
	local time = now - team.memberRefreshTime
	if time >= TEAM_MEMBER_REFRESH_TIME then
		sendLists(team)	
		team.memberRefreshTime = now
	end
end

-- 5s timer
function checkTeamMember()
	for teamId,team in pairs(Team) do
			local change = checkOffline(team) -- 检查T成员 
			if not change then
				memberRefresh(team)			  -- 成员信息刷新	
			else
				sendLists(team)	
			end
	end
end

--队伍创建回调
function onTeamCreateCB(uuid)
	return uuid
end

--队伍进人回调before （注意 这个回调发生的时候 人还没有加入队伍的数据中）
function onAddMemberBeforeCB(team,uuid)
  CopyCallbackW.onAddMemberBeforeCB(team, uuid)
	return team, uuid
end

--队伍进人回调after （注意 这个回调发生的时候 人已经加入队伍的数据中）
function onAddMemberAfterCB(team, uuid)
  CopyCallbackW.onAddMemberAfterCB(team, uuid)
  return team, uuid
end

-- 队伍出人回调before （注意 这个回调发生的时候 人还在队伍的数据中）
function onDelMemberBeforeCB(team,uuid)
  CopyCallbackW.onDelTeamMemberBeforeCB(team, uuid)
end

-- 队伍出人回调after （注意 这个回调发生的时候 人不在队伍的数据中）
function onDelMemberAfterCB(team,uuid)
  CopyCallbackW.onDelTeamMemberAfterCB(team, uuid)
end

-- 队伍成员上线回调
function onUserOnlineCB(team, uuid)
  return team, uuid
end

-- 队伍解散回调
function onDismissCB(team)
  CopyCallbackW.onTeamDismissCB(team)
end

-- 队长改变回调
function onChangeLeaderCB(team, uuid)
  CopyCallbackW.onTeamChangeLeaderCB(team, uuid)
end

fds = fds or {}
local function getSameSceneFds(human)
	local team = getTeamByUuid(human._id)
	if not team then
		return
	end
	for key in ipairs(fds) do 
		fds[key] = nil
	end
	local onlineUuid = Human.onlineUuid
	for i = 1, TEAM_MAX_MEMBER_COUNT do
		if team[i] then
			local member = onlineUuid[team[i].uuid]
			if member and human._id ~= member._id and human.scene_id == member.scene_id and member.fd then
				fds[#fds + 1] = member.fd
			end
		end
	end
	fds[0] = #fds
	return fds
end

--血量变化回调
function onHpChange(human)
	local team = getTeamByUuid(human._id)
	if not team then
		return
	end
	local msgRet = Msg.gc.GC_TEAM_SIMPLE_LIST
	msgRet.member.uuid = human._id
	msgRet.member.hp = human.db.hp
	msgRet.member.mapID = human.db.map_id 
	msgRet.member.x = human.db.x
	msgRet.member.y = human.db.y
	msgRet.member.hpMax = human.db.MaxHp
	local fds = getSameSceneFds(human)
	if not fds or #fds == 0 then
		return
	end
	Msg.sendMulti(msgRet,fds)
end
InnerDataManager.Register(InnerDataDefine.INNERDATA_TYPE_HPCHANGE, onHpChange)



-- 获取组队成员名字信息
function getTeamNameInfoLog(team)
	
	local name1,name2,name3,name4,name5
	if team[1] then
		name1 = team[1].name
	end
	
	if team[2] then
		name2 = team[2].name
	end
	
	if team[3] then
		name3 = team[3].name
	end
	
	if team[4] then
		name4 = team[4].name
	end
	
	if team[5] then
		name5 = team[5].name
	end
	return name1 or "",name2 or "",name3 or "",name4 or "",name5 or ""
end


--得到神兵名字
function getPutonSbName(human)
  return sbConfig.shenbing[human.db.putonShenbing] and sbConfig.shenbing[human.db.putonShenbing].sbMingzi or "" 
end
--检查是否显示到组队邀请列表中
function CanAddToTeamShow(human, v)
  if human.scene_id == nil or v.scene_id == nil or human.scene_id ~= v.scene_id then
    return false
  end
  if v._id == human._id then
    return false
  end
  
  if inSameTeam(human._id, v._id) then
    return false
  end
  local team = getTeamByUuid(v._id)
  if team and (team.count >= TEAM_MAX_MEMBER_COUNT or getLeaderUuid(team) ~= v._id)then
    return false
  end
  return true
end

function CG_TEAM_GET_SCENE(human)
  local sendMsg = Msg.gc.GC_TEAM_SEND_SCENE_PER
  sendMsg.list[0] = 0
  for k,v in pairs(Human.onlineUuid) do
    if CanAddToTeamShow(human, v) then
      sendMsg.list[0] = sendMsg.list[0] + 1
      sendMsg.list[sendMsg.list[0]].name = v.name
      sendMsg.list[sendMsg.list[0]].uuid = v._id
      sendMsg.list[sendMsg.list[0]].sbName = getPutonSbName(v)
      sendMsg.list[sendMsg.list[0]].lv = v.db.lv
      sendMsg.list[sendMsg.list[0]].isTeam = v.db.teamUuidLen > 0 and 1 or 0
    end
    if sendMsg.list[0] >= 30 then break end
  end
  Msg.send(sendMsg, human.fd)
end
